package com.binguo.socket;

import com.alibaba.fastjson.JSONObject;
import com.binguo.model.model.CashierDesk;
import com.binguo.model.model.MenjinBinding;
import com.binguo.model.model.MenjinSocketLog;
import com.binguo.model.repository.CashierDeskRepository;
import com.binguo.model.repository.MenjinBindingRepository;
import com.binguo.model.repository.MenjinSocketLogRepository;
import com.binguo.socket.service.MenJinSocketService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import tk.mybatis.mapper.entity.Condition;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author yuritian
 * @Title: WebSocketServer
 * @ProjectName binguoDevelop
 * @Description: TODO
 * @date 2020-02-1313:34
 */

@Component
@ServerEndpoint(value = "/websocket")
public class SocketService {
    private static int onlineCount = 0;
    public static ConcurrentHashMap<String, SocketService> socketSet = new ConcurrentHashMap<>();

    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;
    private static Logger logger = LoggerFactory.getLogger(SocketService.class);
    private String id;

    private static CashierDeskRepository cashierDeskRepository;
    private static MenJinSocketService menJinSocketService;
    private static MenjinBindingRepository menjinBindingRepository;
    private static MenjinSocketLogRepository menjinSocketLogRepository;

    // 注入的时候，给类的 service 注入
    @Autowired
    public void setChatService(CashierDeskRepository cashierDeskRepository,
                               MenJinSocketService menJinSocketService,
                               MenjinBindingRepository menjinBindingRepository,
                               MenjinSocketLogRepository menjinSocketLogRepository) {
        SocketService.cashierDeskRepository = cashierDeskRepository;
        SocketService.menJinSocketService = menJinSocketService;
        SocketService.menjinBindingRepository = menjinBindingRepository;
        SocketService.menjinSocketLogRepository = menjinSocketLogRepository;
    }

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        String serialNo = session.getRequestParameterMap().get("SerialNo").get(0);
        Condition condition = new Condition(CashierDesk.class);
        condition.or().andEqualTo("ccode", serialNo)
                .andEqualTo("deleted", 0);
        List<CashierDesk> deskList = cashierDeskRepository.findByCondition(condition);
        if (null == deskList || deskList.size() == 0) {
            this.session = session;
            Condition bindingCondition = new Condition(MenjinBinding.class);
            bindingCondition.or().andEqualTo("ccode",serialNo);
            List<MenjinBinding> menjinBindingList = menjinBindingRepository.findByCondition(bindingCondition);
            if (null == menjinBindingList || menjinBindingList.size() == 0) {
                MenjinBinding menjinBinding = new MenjinBinding();
                menjinBinding.setCcode(serialNo);
                menjinBinding.setCreatetime(new Date());
                menjinBinding.setStatus(0);
                menjinBindingRepository.save(menjinBinding);
                this.id = "bingDing" + menjinBinding.getId();
            }else {
                this.id = "bingDing" + menjinBindingList.get(0).getId();
            }
            socketSet.put(id, this);
            addOnlineCount();
            logger.error("该机器未在系统内注册,SN码为:"+serialNo);
        } else {
            this.session = session;
            this.id = deskList.get(0).getId().toString();
            //this.id = "bingDing17";
            if (socketSet.get(this.id) != null) {
                logger.error("SN码已经注册,SN码为:" + serialNo);
            } else {
                socketSet.put(id, this);
                addOnlineCount();
                logger.info(serialNo + "注册成功");
            }
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        //从set中删除
        socketSet.remove(this);
        //在线数减1
        subOnlineCount();
        logger.info("有一连接关闭！当前在线人数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session){
        String serialNo = session.getRequestParameterMap().get("SerialNo").get(0);
        logger.info("来自客户端"+serialNo+"的消息:" + message);
        JSONObject msgJson = JSONObject.parseObject(message);
        menJinSocketService.getMessageFormDesk(msgJson);
        System.out.println(msgJson.toJSONString());
    }

    /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        logger.error("发生错误");
        socketSet.remove(this);
        error.printStackTrace();
    }


    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    /**
     * 发送信息给指定ID用户，如果用户不在线则返回不在线信息给自己
     *
     * @param message
     * @param sendUserId
     * @throws IOException
     */
    public static void sendtoUser(String message, String sendUserId,Integer logId) {
        MenjinSocketLog log = menjinSocketLogRepository.findById(logId);
        try {
            logger.info("sendUserId:"+sendUserId);
            socketSet.get(sendUserId).sendMessage(message);
            log.setErrorCode("0");
            menjinSocketLogRepository.update(log);
            logger.info("发送成功:"+message);
        } catch (IOException e) {
            socketSet.remove(sendUserId);
            subOnlineCount();
            logger.error("发送失败"+e.getMessage());
        }
    }

    public boolean changeBindingDesk(String oldId,String id){
        if (socketSet.get(oldId) != null) {
            socketSet.put(id, socketSet.get(oldId));
            socketSet.remove(oldId);
            return true;
        }else {
            return false;
        }
    }



    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        SocketService.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        SocketService.onlineCount--;
    }
}